package abstergo.tbs.betterasyc.AsycBase;

import android.content.Context;
import android.os.Handler;
import android.os.Looper;

import java.io.Closeable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class AsycWorker<TP,TR> implements Closeable
{
    private Context context;
    private IAsycErrorAction<TP,TR> errorAction=new DefaultErrorHandle<>();
    private IAsycBackgroundAction<TP,TR> backgroundAction;
    private IAsycResultAction<TR> resultAction;
    private IAsycHttpProgressUpdateAction progressUpdateAction;
    private ExecutorService executorService;
    private Handler resulthandler =new Handler(Looper.getMainLooper());

    int tn;boolean ac,isInit=false;

    public AsycWorker<TP,TR> Init(int threadnumber,boolean autoclose)
    {
        this.close();
        ac=autoclose;
        tn=threadnumber;
        executorService= Executors.newFixedThreadPool(tn);
        isInit=true;
        return this;
    }
    public AsycWorker()
    {
    }
    public AsycWorker(int n)
    {
        Init(n,false);
    }


    public IAsycErrorAction<TP,TR> getErrorAction() {
        return errorAction;
    }
    public AsycWorker<TP,TR> setErrorAction(IAsycErrorAction<TP,TR> errorAction) {
        this.errorAction = errorAction;
        return this;
    }

    public IAsycHttpProgressUpdateAction getProgressUpdateAction() {
        return progressUpdateAction;
    }

    public IAsycResultAction<TR> getResultAction() {
        return resultAction;
    }

    public IAsycBackgroundAction<TP, TR> getBackgroundAction() {
        return backgroundAction;
    }

    public AsycWorker<TP,TR> setProgressUpdateAction(IAsycHttpProgressUpdateAction progressUpdateAction) {
        this.progressUpdateAction = progressUpdateAction;
        return this;
    }

    public AsycWorker<TP,TR> setResultAction(IAsycResultAction<TR> resultAction) {

        this.resultAction = resultAction;
        return this;
    }

    public AsycWorker<TP,TR> setBackgroundAction(IAsycBackgroundAction<TP,TR> backgroundAction) {
        this.backgroundAction = backgroundAction;
        return this;
    }

    public AsycWorker<TP,TR> setContext(Context context) {
        this.context = context;
        return this;
    }

    public boolean isInit() {
        return isInit;
    }
    public boolean isAutoClose()
    {
        return ac;
    }
    public int getThreadCount()
    {
        return tn;
    }

    public Context getContext() {
        return context;
    }
    public void Run(TP... parmas)
    {
        if (isInit())
        {
            executorService.submit(new Runnable() {
                @Override
                public void run() {
                   AsycResult<TR> result= doInBackground(parmas);
                   resultDoing(result);
                }
            });
        }
    }
    private void resultDoing(AsycResult<TR> result)
    {
        resulthandler.post(new Runnable() {
            @Override
            public void run() {
                onPostExecute(result);
                if(isAutoClose()) {
                    close();
                }
            }
        });
    }


    private void onPostExecute(AsycResult<TR> asycResult) {
        if(asycResult.getCode()==1)
        {
            if(resultAction!=null)
                resultAction.ResultFunction(asycResult.getResult());
        }
        else
        {
            if(errorAction!=null)
                errorAction.Handle(asycResult,this);
        }
    }

    private AsycResult<TR> doInBackground(TP... tps)
    {
        if(backgroundAction!=null)
        {
            AsycResult result=new AsycResult();
            TR obj;
            try {
                  obj=backgroundAction.BackGroundAction(tps);
                  result.setResult(obj);
            }catch (Exception ex)
            {
                if(errorAction!=null)
                {
                    result.setCode(errorAction.ErrorCode(ex,tps));
                }
                else
                    result.setCode(AsycResult.FAIL);
            }
            return result;
        }
        throw new RuntimeException("空后台任务");

    }

    @Override
    public void close() {
        if(executorService!=null)
        {
            if(!executorService.isShutdown())
            {
                executorService.shutdownNow();
                isInit=false;
            }
        }
    }
}